package com.tlgen.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.tlgen.config.ApplicationContextRegister;
import com.tlgen.model.AnnoClass;
import com.tlgen.model.DingTalk;
import com.tlgen.model.FieldVO;
import com.tlgen.service.RefreshService;
import com.tlgen.utils.ReflectUtils;
import com.tlgen.utils.ScanUtils;
import com.tlgen.utils.StringUtils;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;

import static com.tlgen.utils.ReflectUtils.*;

@Service
public class RefreshServiceImpl implements RefreshService {

    @Override
    public void refreshBean() {

        // 将 applicationContext 转换为 ConfigurableApplicationContext
        ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) ApplicationContextRegister.getApplicationContext();

        // 获取 bean 工厂并转换为 DefaultListableBeanFactory
        DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableApplicationContext.getBeanFactory();

        // 通过BeanDefinitionBuilder创建 bean 定义
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(DingTalk.class);
        // 动态为该 bean 类添加属性
        beanDefinitionBuilder.addPropertyValue("appKey", "苹果" + UUID.randomUUID());
        // 删除 bean
//        defaultListableBeanFactory.removeBeanDefinition("test");
        // 允许覆盖 bean 定义
        defaultListableBeanFactory.setAllowBeanDefinitionOverriding(true);
        // 注册 bean
        defaultListableBeanFactory.registerBeanDefinition("dingTalk", beanDefinitionBuilder.getRawBeanDefinition());

//        DingTalk test = (DingTalk) ApplicationContextRegister.getBean("dingTalk");

        // 打印测试查看类中属性变化
//        Field[] fields = test.getClass().getDeclaredFields();
//        for (Field field : fields) {
//            System.out.println(field);
//            String fieldName = ReflectUtils.getFieldValueByFieldName(field.getName(), test);
//            System.out.println(fieldName);
//        }
//
        System.out.println("已刷新 Bean");
    }

    @Override
    public void refreshBean(Class clazz, Object obj) {

        // 获取 bean 的名称
        String beanName = ReflectUtils.getClassName(clazz);

        // 获取经过反射修改后的 obj 中属性和值
        JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(obj));

        // 将 applicationContext 转换为 ConfigurableApplicationContext
        ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) ApplicationContextRegister.getApplicationContext();

        // 获取 bean 工厂并转换为 DefaultListableBeanFactory
        DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableApplicationContext.getBeanFactory();

        // 通过 BeanDefinitionBuilder 创建 bean 定义
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(clazz);

        // 刷新 bean
        for (Map.Entry<String, Object> entry : jsonObject.entrySet()) {
            // 动态为该 bean 类添加属性
            beanDefinitionBuilder.addPropertyValue(entry.getKey(), entry.getValue());
        }

        // 允许覆盖 bean 定义
        defaultListableBeanFactory.setAllowBeanDefinitionOverriding(true);
        // 注册 bean
        defaultListableBeanFactory.registerBeanDefinition(StringUtils.uncapFirst(beanName), beanDefinitionBuilder.getRawBeanDefinition());

        System.out.println("已刷新 Bean");
    }

    @Override
    public void refreshDefinitionBean() {
        // 扫描注解
        List<AnnoClass> classList = ScanUtils.getDirectAnnotation();
        for (AnnoClass annoClass : classList) {
            List<FieldVO> fieldList = getFieldName(annoClass.getType());
            // 拿到已改变的 obj, 保存后边使用
            Object obj = setAnnoFieldValue(annoClass.getType(),
                    Objects.requireNonNull(getFiledInstance(annoClass.getType(), fieldList.get(0).getFieldName())));
            for (FieldVO vo : fieldList) {
                if (!Objects.equals(vo.getFieldName(), fieldList.get(0).getFieldName()))
                    setAnnoFieldValue(obj, Objects.requireNonNull(getFiledInstance(annoClass.getType(), vo.getFieldName())));
            }
            // 刷新定义 Bean
            refreshBean(annoClass.getType(), obj);
        }
    }

}
